using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Schema;
using OpenComposite.Base.Collections;
using OpenComposite.EII.Designer.Workflow;
using OpenComposite.Mapper;
using OpenComposite.Repository.Properties;

namespace OpenComposite.EII.Controls
{
	[ToolboxItem(false)]
	public partial class UCLogicaActivityBindingMapping : UserControl
	{
		#region Initialization
		protected UCLogicaActivityBindingMapping()
		{
			_logicalActivity = null;
			_capability = null;
			_operation = null;
			InitializeComponent();
		}
		public UCLogicaActivityBindingMapping(Repository.LogicalActivity logicalActivity,
											  Repository.Workflow workflow)
		{
			if ( logicalActivity == null )
				throw new ArgumentNullException("logicalActivity", "Missing Logical Activity.");

			_logicalActivity = logicalActivity;
			_capability = null;
			_operation = null;
			_workflow = workflow;

			InitializeComponent();
		}
		#endregion

		#region Public Members

		#region Events
		public event EventHandler LogicalActivityChanged = null;
		#endregion

		#region Properties
		#endregion

		#endregion

		#region Protected Members

		#region Methods

		protected virtual void OnLogicalActivityChanged()
		{
			display();
			EventHandler tmp = this.LogicalActivityChanged;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);
		}

		#endregion

		#endregion

		#region Private Members

		#region Fields

		private Repository.LogicalActivity _logicalActivity;
		private Repository.Verb _capability;
		private Repository.Operation _operation;
		private Repository.WebService _webService;
		private Repository.WebMethod _webMethod;
		private Repository.HumanActivity _humanActivity;
		private Repository.Workflow _workflow;

		private BindingListEx<Repository.LogicalActivityBinding> _bindings;
		private Repository.LogicalActivityBinding _currentBinding;
		#endregion

		#region Methods
		private void display()
		{
			this.SuspendLayout();
			// clear
			lblLogCapName.Text = "";
			txtWebService.Text = "";
			cmbWebMethod.Items.Clear();
			lblUrl.Text = "";
			lblInputMapping.Image = null;
			lblOutputMapping.Image = null;
			if ( _logicalActivity == null ) {
				lblLogCapName.Text = "INVALID LOGICAL CAPABILITY";
			} else {
				// get webservice
				_webService = _logicalActivity.GetWebService();
				// get webmethod
				_webMethod = _logicalActivity.GetWebMethod();
				// get human activity
				_humanActivity = _logicalActivity.GetHumanActivity();
				// get capability
				_capability = _logicalActivity.Verb;
				// get operation
				_operation = _logicalActivity.GetAssignedOperation();

				// display capability name
				lblLogCapName.Text = _logicalActivity.Name;
				if ( _humanActivity != null ) {
					// display selected human activity
					txtWebService.Text = _webService.Name;
					lblUrl.Text = "URL: " + _webService.Uri;
					toolTips.SetToolTip(lblUrl, _webService.Uri);

					lblHAProperties.Visible = true;
					tableLayoutPanel1.SetColumnSpan(lblUrl, 3);

					cmbWebMethod.Items.AddRange(_webService.GetWebMethods().ToArray());
					if ( _webMethod == null && cmbWebMethod.Items.Count > 0 )
						cmbWebMethod.SelectedIndex = 0;
				} else if ( _webService != null ) {
					// display selected webservice
					txtWebService.Text = _webService.Name;
					lblUrl.Text = "URL: " + _webService.Uri;
					toolTips.SetToolTip(lblUrl, _webService.Uri);

					lblHAProperties.Visible = false;
					tableLayoutPanel1.SetColumnSpan(lblUrl, 5);

					cmbWebMethod.Items.AddRange(_webService.GetWebMethods().ToArray());
					if ( _webMethod == null && cmbWebMethod.Items.Count > 0 )
						cmbWebMethod.SelectedIndex = 0;
				} else {
					lblHAProperties.Visible = false;
					tableLayoutPanel1.SetColumnSpan(lblUrl, 5);
				}
				if ( _webMethod != null ) {
					// display selected webmethod
					if ( cmbWebMethod.Items.Contains(_webMethod) ) {
						cmbWebMethod.SelectedItem = _webMethod;
					} else if ( cmbWebMethod.Items.Count > 0 ) {
						cmbWebMethod.SelectedIndex = 0;
					}
				}
				if ( _capability != null ) { // has capability
					// input mapping?
					if ( _capability.InputBusinessObjectID > 0 ) {
						lblInputMapping.Image =
							_logicalActivity.InputXslt != null ? Resources.png_ok : Resources.png_cancel;
					}
					lblInputMapping.Enabled = ( _capability.InputBusinessObjectID > 0 );
					// output mapping?
					if ( _capability.OutputBusinessObjectID > 0 ) {
						lblOutputMapping.Image =
							_logicalActivity.OutputXslt != null ? Resources.png_ok : Resources.png_cancel;
					}
					lblOutputMapping.Enabled = ( _capability.OutputBusinessObjectID > 0 );
				} else if ( _operation != null ) { // has operation
					// input mapping?
					if ( _operation.InputBusinessObjectId > 0 ) {
						lblInputMapping.Image =
							_logicalActivity.InputXslt != null ? Resources.png_ok : Resources.png_cancel;
					}
					lblInputMapping.Enabled = ( _operation.InputBusinessObjectId > 0 );
					// output mapping?
					if ( _operation.OutputBusinessObjectId > 0 ) {
						lblOutputMapping.Image =
							_logicalActivity.OutputXslt != null ? Resources.png_ok : Resources.png_cancel;
					}
					lblOutputMapping.Enabled = ( _operation.OutputBusinessObjectId > 0 );
				}
			}
			this.ResumeLayout(true);
		}
		private void displayBindings()
		{
			if ( _logicalActivity == null )
				return;

			// fill bindings combobox
			// get other bindings
			_bindings = _logicalActivity.GetBindings();
			if ( _bindings == null )
				_bindings = new BindingListEx<OpenComposite.EII.Repository.LogicalActivityBinding>();
			if ( _bindings.Count == 0 && _logicalActivity.WebServiceID > 0 ) {
				Repository.LogicalActivityBinding bind = new OpenComposite.EII.Repository.LogicalActivityBinding(_logicalActivity);
				bind.LogicalActivityID = _logicalActivity.ID;
				bind.WebServiceID = _logicalActivity.WebServiceID;
				bind.WebMethodID = _logicalActivity.WebMethodID;
				bind.InputConnections = _logicalActivity.InputConnections;
				bind.InputXslt = _logicalActivity.InputXslt;
				bind.OutputConnections = _logicalActivity.OutputConnections;
				bind.OutputXslt = _logicalActivity.OutputXslt;
				bind.ExtendedProperties = _logicalActivity.ExtendedProperties;
				_logicalActivity.SetBinding(bind);
				_bindings = _logicalActivity.GetBindings();
			}
			// check for deleted
			foreach ( Repository.LogicalActivityBinding lab in _bindings.ToArray() ) {
				if ( lab.IsDeleted ) {
					_bindings.Remove(lab);
					_logicalActivity.DeleteBinding(lab);
				}
			}
			cmbSelectOtherBindings.Items.Clear();
			cmbSelectOtherBindings.Items.AddRange(_bindings.ToArray());
			findCurrentBinding();
		}
		private void doMapping(bool isInput)
		{
			if ( _webMethod == null )
				return;

			string connections, sXslt, codeMapping;
			XmlSchema xsdSource, xsdTarget;
			//XmlSchema xsdIn, xsdOut;
			FormMapping frm = new FormMapping();
			if ( isInput ) {
				sXslt = _logicalActivity.InputXslt == null ? null : _logicalActivity.InputXslt.InnerXml;
				connections = _logicalActivity.InputConnections;
				xsdSource = _logicalActivity.GetSubscribedCompoundXmlSchema();
				xsdTarget = _logicalActivity.InputBusinessObjectSchema;//_webMethod.InputSchema;
				codeMapping = _logicalActivity.ExtendedProperties.InputCodeMapping;
			} else {
				sXslt = _logicalActivity.OutputXslt == null ? null : _logicalActivity.OutputXslt.InnerXml;
				connections = _logicalActivity.OutputConnections;
				xsdSource = _webMethod.OutputSchema;
				xsdTarget = _logicalActivity.OutputBusinessObjectSchema;
				codeMapping = _logicalActivity.ExtendedProperties.OutputCodeMapping;
			}
			frm.InitializeMapper(xsdSource, xsdTarget, sXslt, connections, codeMapping);
			frm.UseCodeMapping = _logicalActivity.ExtendedProperties.UseCodeMapping;
			//frm.HeaderText = _logicalActivity.GenerateHeaderText();
			if ( frm.ShowDialog() == DialogResult.OK ) {
				XsltDocument xslt = frm.GetMapping(out connections);
				if ( isInput ) {
					_logicalActivity.InputConnections = connections;
					_logicalActivity.InputXslt = xslt;
					if ( _currentBinding != null ) {
						_currentBinding.InputConnections = connections;
						_currentBinding.InputXslt = xslt;
					}
					if ( _logicalActivity.InputXslt != null &&
						 _logicalActivity.InputXslt.DocumentElement.ChildNodes.Count > 0 )
						lblInputMapping.Image = Resources.png_ok;
					else
						lblInputMapping.Image = Resources.png_cancel;
				} else {
					_logicalActivity.OutputConnections = connections;
					_logicalActivity.OutputXslt = xslt;
					if ( _currentBinding != null ) {
						_currentBinding.OutputConnections = connections;
						_currentBinding.OutputXslt = xslt;
					}
					if ( _logicalActivity.OutputXslt != null &&
						 _logicalActivity.OutputXslt.DocumentElement.ChildNodes.Count > 0 )
						lblOutputMapping.Image = Resources.png_ok;
					else
						lblOutputMapping.Image = Resources.png_cancel;
				}
				_logicalActivity.Save();
				_logicalActivity.SetBinding(_currentBinding);
			}
		}

		private void findCurrentBinding()
		{
			int maxWidth = 0;
			Graphics g = cmbSelectOtherBindings.CreateGraphics();
			foreach ( Repository.LogicalActivityBinding bind in _bindings ) {
				SizeF szf = g.MeasureString(bind.ToString(), cmbSelectOtherBindings.Font);
				int w = (int)Math.Ceiling(szf.Width);
				if ( maxWidth < w ) maxWidth = w;
				if ( bind.WebServiceID == _logicalActivity.WebServiceID &&
					 bind.WebMethodID == _logicalActivity.WebMethodID ) {
					_currentBinding = bind;
					cmbSelectOtherBindings.SelectedItem = _currentBinding;
				}
			}
			if ( maxWidth > 0 )
				cmbSelectOtherBindings.DropDownWidth = maxWidth;
			g.Dispose();
		}
		#endregion

		#region Event Handlers

		private void txtWebService_DragOver(object sender, DragEventArgs e)
		{
			if ( e.Data.GetDataPresent(typeof(Repository.WebService)) ||
				 e.Data.GetDataPresent(typeof(Repository.HumanActivity)) ) {
				e.Effect = DragDropEffects.Link;
			} else {
				e.Effect = DragDropEffects.None;
			}
		}

		private void txtWebService_DragDrop(object sender, DragEventArgs e)
		{
			bool changed = false;
			if ( e.Data.GetDataPresent(typeof(Repository.WebService)) ) {
				_webService = e.Data.GetData(typeof(Repository.WebService)) as Repository.WebService;
				if ( _webService != null && _logicalActivity.WebServiceID != _webService.ID ) {
					_logicalActivity.WebServiceID = _webService.ID;
					_logicalActivity.HumanActivityID = -1;
					_logicalActivity.Save();
					_humanActivity = null;
					changed = true;
				}
			} else if ( e.Data.GetDataPresent(typeof(Repository.HumanActivity)) ) {
				_humanActivity =
					e.Data.GetData(typeof(Repository.HumanActivity)) as Repository.HumanActivity;
				if ( _humanActivity != null ) {
					_webService = _humanActivity.WebService;
					if ( _webService != null && _logicalActivity.HumanActivityID != _humanActivity.ID ) {
						_logicalActivity.WebServiceID = _webService.ID;
						_logicalActivity.HumanActivityID = _humanActivity.ID;
						_logicalActivity.Save();
						changed = true;
					}
				}
			}
			if ( changed ) {
				if ( _currentBinding == null ||
					 _currentBinding.WebServiceID != _logicalActivity.WebServiceID ||
					 _currentBinding.WebMethodID != _logicalActivity.WebMethodID ) {
					if ( _currentBinding != null ) {
						_logicalActivity.SetBinding(_currentBinding);
					}
					_logicalActivity.InputConnections = null;
					_logicalActivity.InputXslt = null;
					_logicalActivity.OutputConnections = null;
					_logicalActivity.OutputXslt = null;
					_logicalActivity.ExtendedProperties.BusinessRuleOutputPath = "";
					_logicalActivity.ExtendedProperties.HumanComponentProperties = new OpenComposite.EII.Repository.HumanComponentProperties();
					display();

					Repository.LogicalActivityBinding bind = new OpenComposite.EII.Repository.LogicalActivityBinding(_logicalActivity);
					bind.WebServiceID = _logicalActivity.WebServiceID;
					bind.WebMethodID = _logicalActivity.WebMethodID;
					bind.HumanActivityID = _logicalActivity.HumanActivityID;
					_logicalActivity.SetBinding(bind);

					displayBindings();
				}
			}
		}

		private void txtWebService_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{
		}

		private void txtWebService_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{
		}

		private void cmbWebMethod_SelectedIndexChanged(object sender, EventArgs e)
		{
			if ( !this.DesignMode ) {
				Repository.WebMethod wm = cmbWebMethod.SelectedItem as Repository.WebMethod;
				if ( wm != _webMethod && _logicalActivity.WebMethodID != wm.ID ) {
					_logicalActivity.WebMethodID = wm.ID;
					_logicalActivity.Save();
					if ( _currentBinding != null ) {
						_currentBinding.WebMethodID = _logicalActivity.WebMethodID;
						_logicalActivity.SetBinding(_currentBinding);
						displayBindings();
					}
					display();
				}
			}
		}

		private void lblInputMapping_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			if ( !this.DesignMode )
				doMapping(true);
		}
		private void lblOutputMapping_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			if ( !this.DesignMode )
				doMapping(false);
		}
		private void lblHAProperties_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			if ( _logicalActivity != null ) {
				FormHumanTaskProperties frm = new FormHumanTaskProperties(_logicalActivity, _workflow);
				frm.ShowDialog();
			}
		}

		private void lblUrl_Click(object sender, EventArgs e)
		{

		}

		private void UCLogicalActivityBindingMapping_Load(object sender, EventArgs e)
		{
			if ( !this.DesignMode ) {
				display();
				displayBindings();
			}
		}

		#endregion

		private void cmbSelectOtherBindings_SelectedIndexChanged(object sender, EventArgs e)
		{
			Repository.LogicalActivityBinding bind = cmbSelectOtherBindings.SelectedItem as Repository.LogicalActivityBinding;
			if ( bind != null && ( _currentBinding == null || !_currentBinding.Equals(bind) ) ) {
				if ( _currentBinding != null ) {
					_currentBinding.WebServiceID = _logicalActivity.WebServiceID;
					_currentBinding.WebMethodID = _logicalActivity.WebMethodID;
					_currentBinding.HumanActivityID = _logicalActivity.HumanActivityID;
					_currentBinding.InputConnections = _logicalActivity.InputConnections;
					_currentBinding.InputXslt = _logicalActivity.InputXslt;
					_currentBinding.OutputConnections = _logicalActivity.OutputConnections;
					_currentBinding.OutputXslt = _logicalActivity.OutputXslt;
					_currentBinding.ExtendedProperties = _logicalActivity.ExtendedProperties;
					_logicalActivity.SetBinding(_currentBinding);
				}
				_currentBinding = bind;
				_logicalActivity.WebServiceID = bind.WebServiceID;
				_logicalActivity.WebMethodID = bind.WebMethodID;
				_logicalActivity.HumanActivityID = bind.HumanActivityID;
				_logicalActivity.InputConnections = bind.InputConnections;
				_logicalActivity.InputXslt = bind.InputXslt;
				_logicalActivity.OutputConnections = bind.OutputConnections;
				_logicalActivity.OutputXslt = bind.OutputXslt;
				if ( bind.ExtendedProperties != null ) {
					_logicalActivity.ExtendedProperties.BusinessRuleOutputPath = bind.ExtendedProperties.BusinessRuleOutputPath;
					_logicalActivity.ExtendedProperties.HumanComponentProperties.AssemblyName = bind.ExtendedProperties.HumanComponentProperties.AssemblyName;
					_logicalActivity.ExtendedProperties.HumanComponentProperties.FormName = bind.ExtendedProperties.HumanComponentProperties.FormName;
					_logicalActivity.ExtendedProperties.HumanComponentProperties.Participants = bind.ExtendedProperties.HumanComponentProperties.Participants;
				}
				display();
			}
		}

		#endregion

	}

}
